/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2020年9月3日
 */
package com.massyframework.beanskin.runtime.modular.assembly.handling;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;

import com.massyframework.beanskin.assembly.Assembly;
import com.massyframework.beanskin.assembly.handling.HandlerNotFoundException;
import com.massyframework.beanskin.assembly.handling.HandlerRegistration;
import com.massyframework.beanskin.assembly.handling.HandlerRegistry;

/**
 * 处理器注册器
 * 
 * <p>
 * 提供注册器注册、查询方法。
 * @author huangkh
 *
 */
abstract class AbstractHandlerRegistry implements HandlerRegistry {

	private final List<RegistrationImpl<?>> registrations = new CopyOnWriteArrayList<>();
	
	/**
	 * 
	 */
	public AbstractHandlerRegistry() {
	}

	@Override
	public <H> H findHandler(Class<H> handlerType) {
		for (RegistrationImpl<?> registration: this.registrations){
            Class<?> type = registration.getHandler().getClass();
            if (handlerType.isAssignableFrom(type)){
                return handlerType.cast(registration.getHandler());
            }
        }
        return null;
	}
	
	
	
	@Override
	public <H> H getHandler(Class<H> handlerType) throws HandlerNotFoundException {
		H result = this.findHandler(handlerType);
        if (result == null){
            throw new HandlerNotFoundException(handlerType, this.getAssociatedAssembly());
        }
        return result;
	}

	@Override
	public <H> List<H> getHandlers(Class<H> handlerType) {
		List<H> result = new ArrayList<>();
        for (RegistrationImpl<?> registration: this.registrations){
            Class<?> type = registration.getHandler().getClass();
            if (handlerType.isAssignableFrom(type)){
                result.add(handlerType.cast(registration.getHandler()));
            }
        }
        return result;
	}
	
	

	@Override
	public <T> HandlerRegistration<T> register(T handler) throws Exception {
		RegistrationImpl<T> result = new RegistrationImpl<T>(handler);
        this.initHandler(handler);
        this.registrations.add(result);
        this.logTrace("add handler: " + handler.getClass().getName() + ".");
        return result;
	}
	
	/**
	 * 注销处理器
	 * @param registration {@link RegistrationImpl}
	 * @return {@link boolean}
	 */
	private boolean doUnregister(RegistrationImpl<?> registration){
        if (this.registrations.remove(registration)){
        	this.destroyHandler(registration.getHandler());	
            this.logTrace("remove handler: " + registration.getHandler().getClass().getName() + ".");
            return true;
        }
        return false;
    }
	
	/**
	 * 记录跟踪信息
	 * @param message {@link String},信息
	 */
	protected abstract void logTrace(String message);
	
	/**
     * 记录调试信息
     * @param message {@link String},信息
     */
    protected abstract void logDebug(String message);
    
    /**
     * 记录日志信息
     * @param message {@link String},信息
     */
    protected abstract void logInfo(String message);
    
    /**
     * 记录警告信息及例外
     * @param message {@link String},对例外的描述
     * @param cause {@link Throwable},例外
     */
    protected abstract void logWarn(String message, Throwable cause);
    
    /**
     * 记录错误信息及例外
     * @param message {@link String},错误信息
     * @param cause {@link Throwable},例外
     */
    protected abstract void logError(String message, Throwable cause);
	
	/**
	 * 初始化Handler
	 * @param handler {@link Object}
	 * @throw Exception 初始化期间发生的非预期例外
	 */
	protected abstract void initHandler(Object handler) throws Exception;
	
	/**
	 * 释放Handler
	 * @param handler {@link Object}
	 */
	protected abstract void destroyHandler(Object handler);
	
	/**
	 * 关联的装配件
	 * @return {@link Assembly}
	 */
	public abstract Assembly getAssociatedAssembly();

	/**
	 * 注册凭据实现类
	 * @param <H>
	 */
	private class RegistrationImpl<H> implements HandlerRegistration<H> {

        private final H handler;

        /**
         * 构造方法
         * @param handler {@link H}, 处理器
         */
        public RegistrationImpl(H handler){
            this.handler = Objects.requireNonNull(handler, "\"handler\" cannot be null.");
        }

        /**
         * 注册的处理器
         *
         * @return {@link H}
         */
        @Override
        public H getHandler() {
            return this.handler;
        }

        /**
         * 取消注册
         */
        @Override
        public boolean unregister() {
            return doUnregister(this);
        }
    }
}
